#include "PlayerSystem.h"
#include "PhysicComponents.h"
#include "PositionComponent.h"
#include "GraphicComponents.h"
#include "BulletComponent.h"
#include "BulletSystem.h"
#include "CharacterComponent.h"
#include "ScriptComponent.h"
#include "MathUtiles.h"
#include "Base/BPL.h"

#include "RenderSystem.h"
#include "PhysicSystem.h"
#include "PlayerSystem.h"
#include "BulletSystem.h"
#include "DamageSystem.h"
#include "CameraSystem.h"

#include "GameState.h"

#include <cstdlib>

void PlayerSystem::update(float dt)
{
	// INPUT
	//const sf::Input& input = mpt_app->GetInput();
	sf::Vector2f moveDir(0.0f,0.0f);
	CharacterComponentPtr charEnt = entityManager->getEntity(mpt_playerID)->getAs<CharacterComponent>();
	
	if(sf::Keyboard::isKeyPressed(sf::Keyboard::Q))
	{
		moveDir += sf::Vector2f(-1.0f,0.0f);
		charEnt->orientation = CharacterComponent::LEFT;
	}
	if(sf::Keyboard::isKeyPressed(sf::Keyboard::D))
	{
		moveDir += sf::Vector2f(1.0f,0.0f);
		charEnt->orientation = CharacterComponent::RIGHT;
	}

	JumpingComponentPtr physEnt = entityManager->getEntity(mpt_playerID)->getAs<JumpingComponent>();
	physEnt->jumpState += physEnt->jumpLength*dt;

	if(physEnt->jumpState>1)
		physEnt->jumpState = 1;

	if(moveDir != sf::Vector2f(0.0f,0.0f))
		moveDir = physEnt->speed * normalize(moveDir);
	
	moveDir+=sf::Vector2f(0.0f,physEnt->jumpSpeed*physEnt->jumpState);



	physEnt->moveDirection = moveDir;
}

void PlayerSystem::addEntity(int ent)
{
	if(!entityManager->hasEntity(ent))
		return;

    mpt_entitiesID.insert(ent);
	entityManager->getEntity(ent)->addSystem(this);
	mpt_playerID = ent;
}

void PlayerSystem::getEvent(sf::Event& event)
{

    if(event.type == sf::Event::KeyPressed)
	{
		if(event.key.code == sf::Keyboard::Space)
		{
			JumpingComponentPtr physEnt = entityManager->getEntity(mpt_playerID)->getAs<JumpingComponent>();
			if(!physEnt->jump)
			{
				physEnt->jump = true;
				physEnt->jumpState = -1;
			}
		}
		else if(event.key.code == sf::Keyboard::M)
		{
			// SHOOT
			BPL::EntityPtr playerEnt = entityManager->getEntity(mpt_playerID);
			PositionComponentPtr playerPos(playerEnt->getAs<PositionComponent>());
			PhysicComponentPtr playerPhys(playerEnt->getAs<PhysicComponent>());
			CharacterComponentPtr playerChar(playerEnt->getAs<CharacterComponent>());
			sf::Vector2f position(playerPos->m_position + sf::Vector2f(playerPhys->sizeBox.x/2 + playerPhys->sizeBox.x * playerChar->orientation,playerPhys->sizeBox.y/4 + (std::rand()%8 - 4)));

			BPL::EntityPtr e(new BPL::Entity(entityManager->getNextAvailableID()));
			entityManager->registerDynamicEntity(e, position,0);
			
			ModelGraphicComponentPtr graph (new ModelGraphicComponent);
			DynamicComponentPtr phys (new DynamicComponent);
			PositionComponentPtr pos (new PositionComponent);
			BulletComponentPtr bullet (new BulletComponent);
		
			int sizeTile = entityManager->sizeTile;
			pos->m_position=position;

			graph->model.loadModel("Data/bullet.mdl");
			pos->m_center = graph->model.getCurrentSprite().getOrigin();
			if(playerChar->orientation < 0)
				graph->model.flipX(true);

			phys->speed = 300;
			sf::FloatRect rect = graph->model.getCurrentSprite().getLocalBounds();
			phys->sizeBox = sf::Vector2f(rect.height,rect.width);

			bullet->firstPosition = position;
			bullet->IDlauncher = mpt_playerID;
			bullet->power = 100;
			bullet->rebounds = 0;
			bullet->horizontalOrientation = playerChar->orientation;
			bullet->trajectoire = new TrajectoireLineRandom(0.3);
			bullet->type = BulletComponent::NORMAL;
			
			entityManager->addComponent<GraphicComponent>((BPL::EntityId)e->getID(), graph);
			entityManager->addComponent<PhysicComponent>((BPL::EntityId)e->getID(), phys);
			entityManager->addComponent<PositionComponent>((BPL::EntityId)e->getID(), pos);
			entityManager->addComponent<BulletComponent>((BPL::EntityId)e->getID(), bullet);
			
			GameState* state = static_cast<GameState*>(mpt_parent);
			state->mpt_renderSystem->addEntity(e->getID());
			state->mpt_physicSystem->addEntity(e->getID());
			state->mpt_bulletSystem->addEntity(e->getID());
			state->mpt_damageSystem->addBullet(e->getID());
		}
		else if(event.key.code == sf::Keyboard::P)
		{
			// GRENADE
			BPL::EntityPtr playerEnt = entityManager->getEntity(mpt_playerID);
			PositionComponentPtr playerPos(playerEnt->getAs<PositionComponent>());
			PhysicComponentPtr playerPhys(playerEnt->getAs<PhysicComponent>());
			CharacterComponentPtr playerChar(playerEnt->getAs<CharacterComponent>());
			sf::Vector2f position(playerPos->m_position + sf::Vector2f(playerPhys->sizeBox.x/2 + playerPhys->sizeBox.x * playerChar->orientation,playerPhys->sizeBox.y/4 + std::rand()%8 - 4));

			BPL::EntityPtr e(new BPL::Entity(entityManager->getNextAvailableID()));
			entityManager->registerDynamicEntity(e, position,0);
			
			ModelGraphicComponentPtr graph (new ModelGraphicComponent);
			JumpingComponentPtr phys (new JumpingComponent);
			PositionComponentPtr pos (new PositionComponent);
			BulletComponentPtr bullet (new BulletComponent);
		
			int sizeTile = entityManager->sizeTile;
			pos->m_position=position;
			graph->model.loadModel("Data/grenade.mdl");
			pos->m_center = graph->model.getCurrentSprite().getOrigin();
			sf::FloatRect rect = graph->model.getCurrentSprite().getLocalBounds();
			phys->sizeBox = sf::Vector2f(rect.height,rect.width);

			bullet->firstPosition = position;
			bullet->IDlauncher = mpt_playerID;
			bullet->power = 400;
			bullet->rebounds = 1;
			bullet->range = 100;
			bullet->horizontalOrientation = playerChar->orientation;
			bullet->type = BulletComponent::GRENADE;
			bullet->timeBeforeDeath = 2.0f;
			phys->jumpSpeed = 600.0f;
			phys->jumpLength = 2.75;
			phys->jumpState = -1;
			phys->speed = 150;

			entityManager->addComponent<GraphicComponent>((BPL::EntityId)e->getID(), graph);
			entityManager->addComponent<PhysicComponent>((BPL::EntityId)e->getID(), phys);
			entityManager->addComponent<PositionComponent>((BPL::EntityId)e->getID(), pos);
			entityManager->addComponent<BulletComponent>((BPL::EntityId)e->getID(), bullet);

			GameState* state = static_cast<GameState*>(mpt_parent);
			state->resume();
			state->mpt_renderSystem->addEntity(e->getID());
			state->mpt_physicSystem->addEntity(e->getID());
			state->mpt_bulletSystem->addEntity(e->getID());
			state->mpt_damageSystem->addBullet(e->getID());
		}
	}
}

void PlayerSystem::deleteEntity(int ent)
{
	std::set<int>::iterator itr = mpt_entitiesID.find(ent);
	if(itr != mpt_entitiesID.end())
	{
		mpt_entitiesID.erase(itr);
	}
	if(mpt_playerID == ent)
	{
		mpt_playerID = 0;
	}
	BPL::Logger::log("delete from PlayerSystem");
}